package org.papervision3d.scenes
{
    import flash.utils.getTimer;
    import flash.display.*;
    
    import org.papervision3d.scenes.*;
    import org.papervision3d.core.proto.*;
    
    import org.papervision3d.objects.DisplayObject3D;
    import flash.geom.Rectangle;
    import flash.geom.Point;
    import org.papervision3d.core.geom.DrawTriangle;
    
    // The MovieScene3D class lets you create a scene where each object is rendered in its own container.
    // A scene is the place where objects are placed, it contains the 3D environment.
    public class MovieScene3D extends Scene3D
    {
        // Creates a scene where each object is rendered in its own container.
        // @param    container   The Sprite where the new containers are created.
        public function MovieScene3D(container:Sprite)
        {
            super(container);
    
            this.containerList = new Array();
        }

        // Adds a child DisplayObject3D instance to the scene.
        // If you add a GeometryObject3D symbol, a new DisplayObject3D instance is created.
        // [TODO: If you add a child object that already has a different display object container as a parent, the object is removed from the child list of the other display object container.]
        // @param    child   The GeometryObject3D symbol or DisplayObject3D instance to add as a child of the scene.
        // @param    name    An optional name of the child to add or create. If no name is provided, the child name will be used.
        // @return   The DisplayObject3D instance that you have added or created.
        public override function addChild(child:DisplayObject3D, name:String = null):DisplayObject3D
        {
            child = super.addChild(child, name);
    
            child.container = new Sprite();
            container.addChild(child.container);
            this.containerList.push(child.container);
    
            return child;
        }
    
        public override function clear():void
        {
        	//trace(" clear() ");
            var gfx:Sprite;
            var containerList:Array = this.containerList;
            var i:int = 0;
    
            // Clear all known object
            while (gfx = containerList[i++]) 
                gfx.graphics.clear();
        }
        
        override public function renderCamera(camera:CameraObject3D, callback:TraverseCallback = null):void
        {
            stats.performance = getTimer();
            stats.rendered = 0;
    
            clear();

            for each (var m:MaterialObject3D in this.materials)
            {
                trace("SceneObject3D:materials " + m);
                if (m.animated)
                    m.updateBitmap();
            }

            camera.transformView();

            var objects:Array = this.objects;
            var p:DisplayObject3D;
            var i:Number = objects.length;
            var do_container : Sprite;
    
            if (callback == null)
                callback = new RenderCallback();

            var clip:Rectangle = this.clip;
            
            if (clip == null)
            {
                var lt:Point = container.globalToLocal(new Point(0, 0));
                clip = new Rectangle(lt.x, lt.y, container.stage.stageWidth, container.stage.stageHeight);
            }

            while(p = objects[--i])
            {
            	do_container = p.container;
                callback.init(this, camera, clip)
                if (callback.enter(p))
                {
                    p.project(camera, camera, callback);

                    callback.leave(p);

                    var triangles:Array = callback.list();

                    if (triangles != null)
                    {
                        for each(var triangle:DrawTriangle in triangles)
                        {
                            triangle.render(do_container);
                        }
                        stats.rendered += triangles.length;
                    }
                }
            }

            stats.performance = getTimer() - stats.performance;
            
        }
         
        private var containerList:Array;
    }
}